package jmars.mobile.worker.gephi;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import jmars.mobile.common.Investigator;
import jmars.mobile.datainvestigation.Summary;

/**
 * select [group columns], count, sum(target column1) [, sum(target column2)...] 
 * from data group by [group columns] 
 * order by count desc
 * 
 * @author Jan
 *
 */
public class GPRSServiceNodes implements Investigator {

	@Override
	public Long compute(File[] files, FileWriter writer) throws IOException {
		Long total = 0L;
		FileInputStream fis;
		BufferedReader reader;
		String row;
		String[] cols;
		Map<String,Integer> distinct=new HashMap<String,Integer>();
		Map<String,Integer> sgsnCount=new HashMap<String,Integer>();
		Map<String,Integer> ggsnCount=new HashMap<String,Integer>();
		Map<String,Map<Integer,Double>> nodeSgsnStat=new HashMap<String,Map<Integer,Double>>();
		Map<String,Map<Integer,Double>> nodeGgsnStat=new HashMap<String,Map<Integer,Double>>();
		Map<String,String> nodeType=new HashMap<String,String>();
		Map<Integer,Double> eachNode;
		DecimalFormat df = new DecimalFormat();
		df.applyPattern("0");
		Double tempD;
		int idx;
		for(File inputFile:files){
			fis = new FileInputStream(inputFile);
			reader = new BufferedReader(new InputStreamReader(fis));
			while((row=reader.readLine())!=null){
				cols=row.split(Summary.columnSeperator);
				if(Summary.filterRow(cols,false,true)) continue;
				if(cols.length<20)continue;
				if(cols[18].indexOf(".")==-1)continue;
				if(cols[19].indexOf(".")==-1)continue;
				//SGSN
				idx=18;
				if(!nodeType.containsKey(cols[idx])){
					distinct.put(cols[idx],1);
					nodeType.put(cols[idx], "SGSN");
				}else{
					distinct.put(cols[idx],distinct.get(cols[idx])+1);
					if(nodeType.get(cols[idx]).indexOf("SGSN")==-1)nodeType.put(cols[idx],nodeType.get(cols[idx])+"SGSN");
				}
				if(!sgsnCount.containsKey(cols[idx])){
					sgsnCount.put(cols[idx],1);
					eachNode = new HashMap<Integer,Double>();
					nodeSgsnStat.put(cols[idx], eachNode);
				}else{
					sgsnCount.put(cols[idx],sgsnCount.get(cols[idx])+1);
					eachNode = nodeSgsnStat.get(cols[idx]);
				}
				for(Integer tidx:Summary.targetColumnIdx){
					tempD=Double.parseDouble(cols[tidx]);
					if(!eachNode.containsKey(tidx)){
						eachNode.put(tidx, tempD);
					}else{
						eachNode.put(tidx, eachNode.get(tidx)+tempD);
					}
				}

				//GGSN
				idx=19;
				if(!nodeType.containsKey(cols[idx])){
					distinct.put(cols[idx],1);
					nodeType.put(cols[idx], "GGSN");
				}else{
					distinct.put(cols[idx],distinct.get(cols[idx])+1);
					if(nodeType.get(cols[idx]).indexOf("GGSN")==-1)nodeType.put(cols[idx],nodeType.get(cols[idx])+"GGSN");
				}
				if(!ggsnCount.containsKey(cols[idx])){
					ggsnCount.put(cols[idx],1);
					eachNode = new HashMap<Integer,Double>();
					nodeGgsnStat.put(cols[idx], eachNode);
				}else{
					ggsnCount.put(cols[idx],ggsnCount.get(cols[idx])+1);
					eachNode = nodeGgsnStat.get(cols[idx]);
				}
				for(Integer tidx:Summary.targetColumnIdx){
					tempD=Double.parseDouble(cols[tidx]);
					if(!eachNode.containsKey(tidx)){
						eachNode.put(tidx, tempD);
					}else{
						eachNode.put(tidx, eachNode.get(tidx)+tempD);
					}
				}
				
				total++;
			}
			reader.close();
			fis.close();
			System.out.println(inputFile.getName()+" finished at "+total);
		}
		System.out.print("%total:"+df.format(total)+"\r\n");
		if(distinct.size()<=1000000){
			ArrayList<Entry<String,Integer>> l = new ArrayList<Entry<String,Integer>>(distinct.entrySet());    
	          
	        Collections.sort(l, new Comparator<Map.Entry<String, Integer>>() {    
	            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {    
	                return (int) (o2.getValue() - o1.getValue());    
	            }    
	        });

	        System.out.print("%*****************details******************\r\n%");
	        writer.write("Id,Label,Type,sgsncount,ggsncount");
			for(Integer tidx:Summary.targetColumnIdx){
				writer.write(",SGSN_"+Summary.columns[tidx]);
			}
			for(Integer tidx:Summary.targetColumnIdx){
				writer.write(",GGSN_"+Summary.columns[tidx]);
			}
			writer.write("\r\n");
	        for(String key : nodeType.keySet()) {
	        	writer.write(key+","+key+","+nodeType.get(key).replaceAll("GGSNSGSN","SGSNGGSN"));
	            writer.write(","+(nodeSgsnStat.containsKey(key)?df.format(sgsnCount.get(key)):"0"));
	            writer.write(","+(nodeGgsnStat.containsKey(key)?df.format(ggsnCount.get(key)):"0"));
	            for(Integer tidx:Summary.targetColumnIdx){
		            writer.write(","+(nodeSgsnStat.containsKey(key)?df.format(nodeSgsnStat.get(key).get(tidx)):"0"));
	            }
	            for(Integer tidx:Summary.targetColumnIdx){
		            writer.write(","+(nodeGgsnStat.containsKey(key)?df.format(nodeGgsnStat.get(key).get(tidx)):"0"));
	            }
	            writer.write("\r\n");
	        }
	        
		}
		return total;
	}

}
